﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using System.Text;
using ZO.SmartCore.Helpers;
using ZO.SmartCore.Text;
using ArgumentNullException= ZO.SmartCore.Core.ArgumentNullException;

#endregion

namespace ZO.SmartCore.Security.Cryptography
{
    /// <summary>
    ///     Facade which exposes common cryptography uses. 
    /// </summary>
    public static class Cryptographer
    {

        #region Constructors

        #endregion

        #region Destructor

        #endregion

        #region Fields

        #endregion

        #region Events

        #endregion

        #region Operators

        #endregion

        #region Properties

        #endregion

        #region Methods
        /// <overloads>
        ///		Encrypts data using SymmetricEncrypter. 
        /// </overloads>
        /// <summary>
        ///     Encrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static string EncryptSymmetric(string key, string plaintext)
        {
            return EncryptSymmetric(SymmetricAlgorithm.AES, key, plaintext);
        } // EncryptSymmetric

        /// <overloads>
        ///		Encrypts data using SymmetricEncrypter. 
        /// </overloads>
        /// <summary>
        ///     Encrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static string EncryptSymmetric(string key, string plaintext, CharacterEncoding encoding)
        {
            return EncryptSymmetric(SymmetricAlgorithm.AES, key, plaintext, encoding);
        } // EncryptSymmetric


        /// <summary>
        ///     Encrypts a text using a specified key and algorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static string EncryptSymmetric(SymmetricAlgorithm algorithm, string key, string plaintext)
        {
            if (String.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("key");
            } // if
            if (String.IsNullOrEmpty(plaintext))
            {
                throw new ArgumentNullException("plaintext");
            } // if

            return EncryptSymmetric(algorithm, key, plaintext, CharacterEncoding.None);
        } // EncryptSymmetric


        /// <summary>
        ///     Encrypts a text using a specified key and algorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static string EncryptSymmetric(SymmetricAlgorithm algorithm, string key, string plaintext, CharacterEncoding encoding)
        {
            if (String.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("key");
            } // if
            if (String.IsNullOrEmpty(plaintext))
            {
                throw new ArgumentNullException("plaintext");
            } // if

            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {

                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }

            byte[] plainTextBytes = encoder.GetBytes(plaintext);

            byte[] keyTextBytes = encoder.GetBytes(key);

            byte[] cipherTextBytes;

            SymmetricCryptographer symmetricCryptographer = new SymmetricCryptographer(algorithm, keyTextBytes);
            cipherTextBytes = symmetricCryptographer.Encrypt(plainTextBytes);
            return Convert.ToBase64String(cipherTextBytes);
        } // EncryptSymmetric

        /// <summary>
        ///     Encrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static byte[] EncryptSymmetric(byte[] key, byte[] plaintext)
        {
            return EncryptSymmetric(SymmetricAlgorithm.AES, key, plaintext);
        } // EncryptSymmetric

        /// <summary>
        ///     Encrypts a text using a specified key and alogorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="plaintext">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	   The input for which you want to encrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting encrypted text. 
        /// 	 </para>
        /// </returns>
        public static byte[] EncryptSymmetric(SymmetricAlgorithm algorithm, byte[] key, byte[] plaintext)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            } // if
            if (plaintext == null)
            {
                throw new ArgumentNullException("plaintext");
            } // if

            SymmetricCryptographer symmetricCryptographer = new SymmetricCryptographer(algorithm, key);

            return symmetricCryptographer.Encrypt(plaintext);

        } // EncryptSymmetric


        /// <overloads>
        ///		Decrypts data using SymmetricEncrypter. 
        /// </overloads>
        /// <summary>
        ///     Decrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to Decrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static string DecryptSymmetric(string key, string encryptedText)
        {
            return DecryptSymmetric(SymmetricAlgorithm.AES, key, encryptedText);
        } // DecryptSymmetric

        /// <overloads>
        ///		Decrypts data using SymmetricEncrypter. 
        /// </overloads>
        /// <summary>
        ///     Decrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to Decrypt.
        /// 	 </para>
        /// </param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static string DecryptSymmetric(string key, string encryptedText, CharacterEncoding encoding)
        {
            return DecryptSymmetric(SymmetricAlgorithm.AES, key, encryptedText, encoding);
        } // DecryptSymmetric


        /// <summary>
        ///     Decrypts a text using a specified key and algorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to Decrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static string DecryptSymmetric(SymmetricAlgorithm algorithm, string key, string encryptedText)
        {
            if (String.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("key");
            } // if
            if (String.IsNullOrEmpty(encryptedText))
            {
                throw new ArgumentNullException("encryptedText");
            } // if


            return DecryptSymmetric(algorithm, key, encryptedText, CharacterEncoding.None);

        } // DecryptSymmetric


        /// <summary>
        ///     Decrypts a text using a specified key and algorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.String"/>
        /// 	<para>
        /// 	   The input for which you want to Decrypt.
        /// 	 </para>
        /// </param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static string DecryptSymmetric(SymmetricAlgorithm algorithm, string key, string encryptedText, CharacterEncoding encoding)
        {
            if (String.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("key");
            } // if
            if (String.IsNullOrEmpty(encryptedText))
            {
                throw new ArgumentNullException("encryptedText");
            } // if

            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {
                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }
            byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
            byte[] keyTextBytes = encoder.GetBytes(key);

            byte[] cipherTextBytes;

            SymmetricCryptographer symmetricCryptographer = new SymmetricCryptographer(algorithm, keyTextBytes);
            cipherTextBytes = symmetricCryptographer.Decrypt(encryptedTextBytes);
            return encoder.GetString(cipherTextBytes);

        } // DecryptSymmetric


        /// <summary>
        ///     Decrypts a text using a specified key. 
        /// </summary>
        /// <param name="key">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	   The input for which you want to decrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static byte[] DecryptSymmetric(byte[] key, byte[] encryptedText)
        {
            return DecryptSymmetric(SymmetricAlgorithm.AES, key, encryptedText);
        } // DecryptSymmetric

        /// <summary>
        ///     Decrypts a text using a specified key and alogorithm type. 
        /// </summary>
        /// <param name="algorithm">
        ///     <see cref="T:SmartCore.Security.Cryptography.SymmetricAlgorithm"/>
        /// 	<para>
        /// 	    Symmetric Algorithm Type  
        /// 	 </para>
        /// </param>
        /// <param name="key">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	    secret key for the symmetric algorithm.  
        /// 	 </para>
        /// </param>
        /// <param name="encryptedText">
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	   The input for which you want to decrypt.
        /// 	 </para>
        /// </param>
        /// <returns>
        ///     <see cref="T:System.Array"/>
        /// 	<para>
        /// 	     The resulting plain text. 
        /// 	 </para>
        /// </returns>
        public static byte[] DecryptSymmetric(SymmetricAlgorithm algorithm, byte[] key, byte[] encryptedText)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            } // if
            if (encryptedText == null)
            {
                throw new ArgumentNullException("encryptedText");
            } // if

            SymmetricCryptographer symmetricCryptographer = new SymmetricCryptographer(algorithm, key);
            return symmetricCryptographer.Decrypt(encryptedText);
        } // DecryptSymmetric




        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="algorithm">hash algorithm type.</param>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <returns>The computed hash code.</returns>
        public static string CreateHash(HashAlgorithm algorithm, string plaintext)
        {
            byte[] plainTextBytes = Encoding.Default.GetBytes(plaintext);
            byte[] resultBytes = CreateHash(algorithm, plainTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return Convert.ToBase64String(resultBytes);
        }

        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <returns>The computed hash code.</returns>
        public static string CreateHash(string plaintext)
        {
            byte[] plainTextBytes = Encoding.Default.GetBytes(plaintext);
            byte[] resultBytes = CreateHash(plainTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return Convert.ToBase64String(resultBytes);
        }

        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="algorithm">hash algorithm type.</param>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>The computed hash code.</returns>
        public static string CreateHash(HashAlgorithm algorithm, string plaintext, CharacterEncoding encoding)
        {
            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {

                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }
            byte[] plainTextBytes = encoder.GetBytes(plaintext);
            byte[] resultBytes = CreateHash(algorithm, plainTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return Convert.ToBase64String(resultBytes);
        }

        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <returns>The computed hash code.</returns>
        public static string CreateHash(string plaintext, CharacterEncoding encoding)
        {
            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {

                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }
            byte[] plainTextBytes = encoder.GetBytes(plaintext);
            byte[] resultBytes = CreateHash(plainTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return Convert.ToBase64String(resultBytes);
        }

        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="algorithm">hash algorithm type.</param>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <returns>The computed hash code.</returns>
        public static byte[] CreateHash(HashAlgorithm algorithm, byte[] plaintext)
        {
            if (plaintext == null)
            {
                throw new ArgumentNullException("plaintext");
            } // if

            HashCryptographer encoder = new HashCryptographer(algorithm);
            return encoder.ComputeHash(plaintext);
        }

        /// <summary>
        /// Computes the hash value of plain text using the given hash provider instance
        /// </summary>
        /// <param name="plaintext">The input for which to compute the hash.</param>
        /// <returns>The computed hash code.</returns>
        public static byte[] CreateHash(byte[] plaintext)
        {
            if (plaintext == null)
            {
                throw new ArgumentNullException("plaintext");
            } // if

            HashCryptographer encoder = new HashCryptographer();
            return encoder.ComputeHash(plaintext);
        }

        /// <overrides>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </overrides>
        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes may contain a random "salt" value, two seperately generated
        /// hashes of the same plain text may result in different values. 
        /// </remarks>
        /// <param name="algorithm">hash algorithm.</param>
        /// <param name="plaintext">The input for which you want to compare the hash to.</param>
        /// <param name="hashedText">The hash value for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(HashAlgorithm algorithm, byte[] plaintext, byte[] hashedText)
        {
            HashCryptographer encoder = new HashCryptographer(algorithm);
            return encoder.CompareHash(plaintext, hashedText);

        }

        /// <overrides>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </overrides>
        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes may contain a random "salt" value, two seperately generated
        /// hashes of the same plain text may result in different values. 
        /// </remarks>
        /// <param name="plaintext">The input for which you want to compare the hash to.</param>
        /// <param name="hashedText">The hash value for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(byte[] plaintext, byte[] hashedText)
        {
            HashCryptographer encoder = new HashCryptographer();
            return encoder.CompareHash(plaintext, hashedText);
        }

        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes contain a random "salt" value, two seperately generated
        /// hashes of the same plain text will result in different values. 
        /// </remarks>
        /// <param name="algorithm">hash algorithm.</param>
        /// <param name="plaintext">The input as a string for which you want to compare the hash to.</param>
        /// <param name="hashedText">The hash as a string for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(HashAlgorithm algorithm, string plaintext, string hashedText)
        {
            byte[] plainTextBytes = Encoding.Default.GetBytes(plaintext);
            byte[] hashedTextBytes = Convert.FromBase64String(hashedText);

            bool result = CompareHash(algorithm, plainTextBytes, hashedTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return result;
        }

        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes contain a random "salt" value, two seperately generated
        /// hashes of the same plain text will result in different values. 
        /// </remarks>
        /// <param name="plaintext">The input as a string for which you want to compare the hash to.</param>
        /// <param name="hashedText">The hash as a string for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(string plaintext, string hashedText)
        {
            byte[] plainTextBytes = Encoding.Default.GetBytes(plaintext);
            byte[] hashedTextBytes = Convert.FromBase64String(hashedText);

            bool result = CompareHash(plainTextBytes, hashedTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return result;
        }

        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes contain a random "salt" value, two seperately generated
        /// hashes of the same plain text will result in different values. 
        /// </remarks>
        /// <param name="algorithm">hash algorithm.</param>
        /// <param name="plaintext">The input as a string for which you want to compare the hash to.</param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <param name="hashedText">The hash as a string for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(HashAlgorithm algorithm, string plaintext, string hashedText, CharacterEncoding encoding)
        {
            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {

                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }

            byte[] plainTextBytes = encoder.GetBytes(plaintext);
            byte[] hashedTextBytes = Convert.FromBase64String(hashedText);

            bool result = CompareHash(algorithm, plainTextBytes, hashedTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return result;
        }

        /// <summary>
        /// Compares plain text input with a computed hash using the given hash provider instance.
        /// </summary>
        /// <remarks>
        /// Use this method to compare hash values. Since hashes contain a random "salt" value, two seperately generated
        /// hashes of the same plain text will result in different values. 
        /// </remarks>
        /// <param name="plaintext">The input as a string for which you want to compare the hash to.</param>
        /// <param name="encoding">encoding used to convert text to bytes</param>
        /// <param name="hashedText">The hash as a string for which you want to compare the input to.</param>
        /// <returns><c>true</c> if plainText hashed is equal to the hashedText. Otherwise, <c>false</c>.</returns>
        public static bool CompareHash(string plaintext, string hashedText, CharacterEncoding encoding)
        {
            Encoding encoder;

            if (encoding == CharacterEncoding.None)
            {
                encoder = Encoding.Default;
            }
            else
            {

                encoder = Encoding.GetEncoding(ReflectionHelper.GetDescription(encoding));
            }


            byte[] plainTextBytes = encoder.GetBytes(plaintext);
            byte[] hashedTextBytes = Convert.FromBase64String(hashedText);

            bool result = CompareHash(plainTextBytes, hashedTextBytes);
            ByteHelper.GetRandomBytes(plainTextBytes);
            return result;
        }
        #endregion
    }
}
